κ°λ ₯νκ³ νμ -μΈμ΄νν μν λ¨Έμ μ ꡬμΆνλ κ°λ ₯ν λκ΅¬μΈ TypeScript ꡬλ³λ μ λμ¨μ νμν΄ λ³΄μΈμ. μν μ μ, μ ν μ²λ¦¬, κ·Έλ¦¬κ³ μ½λ μ λ’°μ± ν₯μμ μν TypeScriptμ νμ μμ€ν νμ©λ²μ λ°°μ보μΈμ.
TypeScript ꡬλ³λ μ λμ¨: νμ -μΈμ΄ν μν λ¨Έμ ꡬμΆνκΈ°
μννΈμ¨μ΄ κ°λ° μμμμ μ ν리μΌμ΄μ μνλ₯Ό ν¨κ³Όμ μΌλ‘ κ΄λ¦¬νλ κ²μ λ§€μ° μ€μν©λλ€. μν λ¨Έμ μ 볡μ‘ν μν κΈ°λ° μμ€ν μ λͺ¨λΈλ§νκΈ° μν κ°λ ₯ν μΆμνλ₯Ό μ 곡νμ¬, μμΈ‘ κ°λ₯ν λμμ 보μ₯νκ³ μμ€ν λ‘μ§μ λν μΆλ‘ μ λ¨μνν©λλ€. TypeScriptλ κ°λ ₯ν νμ μμ€ν μ ν΅ν΄ ꡬλ³λ μ λμ¨(νκ·Έλ μ λμ¨ λλ λμμ λ°μ΄ν° νμ μ΄λΌκ³ λ ν¨)μ μ¬μ©νμ¬ νμ -μΈμ΄νν μν λ¨Έμ μ ꡬμΆνλ νμμ μΈ λ©μ»€λμ¦μ μ 곡ν©λλ€.
ꡬλ³λ μ λμ¨(Discriminated Unions)μ΄λ 무μμΈκ°μ?
ꡬλ³λ μ λμ¨μ μ¬λ¬ λ€λ₯Έ νμ μ€ νλκ° λ μ μλ κ°μ λνλ΄λ νμ μ λλ€. μ λμ¨μ λ©€λ²λ‘ μλ €μ§ κ° νμ λ€μ ꡬλ³μ(discriminant) λλ νκ·Έ(tag)λΌκ³ λΆλ¦¬λ 곡ν΅μ μ΄κ³ κ³ μ ν μμ±μ 곡μ ν©λλ€. μ΄ κ΅¬λ³μλ TypeScriptκ° νμ¬ μ λμ¨μ μ΄λ€ λ©€λ²κ° νμ±νλμ΄ μλμ§ μ ννκ² νμ ν μ μκ² νμ¬, κ°λ ₯ν νμ κ²μ¬μ μλ μμ±μ κ°λ₯νκ² ν©λλ€.
μ νΈλ±μ μκ°ν΄λ³΄μΈμ. μ νΈλ±μ λΉ¨κ°, λ Έλ, μ΄λ‘ μΈ κ°μ§ μν μ€ νλμΌ μ μμ΅λλ€. 'μμ' μμ±μ΄ ꡬλ³μ μν μ νμ¬ μ νΈλ±μ΄ μ νν μ΄λ€ μνμ μλμ§ μλ €μ€λλ€.
μν λ¨Έμ μ ꡬλ³λ μ λμ¨μ μ¬μ©νλ μ΄μ λ 무μμΈκ°μ?
ꡬλ³λ μ λμ¨μ TypeScriptμμ μν λ¨Έμ μ ꡬμΆν λ λͺ κ°μ§ μ£Όμ μ΄μ μ μ 곡ν©λλ€:
- νμ μμ μ±(Type Safety): μ»΄νμΌλ¬λ λͺ¨λ κ°λ₯ν μνμ μ νμ΄ μ¬λ°λ₯΄κ² μ²λ¦¬λλμ§ νμΈν μ μμ΄, μμμΉ λͺ»ν μν μ νκ³Ό κ΄λ ¨λ λ°νμ μ€λ₯λ₯Ό λ°©μ§ν©λλ€. μ΄λ νΉν ν¬κ³ 볡μ‘ν μ ν리μΌμ΄μ μμ μ μ©ν©λλ€.
- μ² μ μ± κ²μ¬(Exhaustiveness Checking): TypeScriptλ μ½λκ° μν λ¨Έμ μ λͺ¨λ κ°λ₯ν μνλ₯Ό μ²λ¦¬νλλ‘ λ³΄μ₯νμ¬, 쑰건문μ΄λ switch-case λ¬Έμμ μνκ° λλ½λλ©΄ μ»΄νμΌ νμμ μλ €μ€λλ€. μ΄λ μμμΉ λͺ»ν λμμ λ°©μ§νκ³ μ½λλ₯Ό λ κ²¬κ³ νκ² λ§λλλ€.
- κ°λ μ± ν₯μ: ꡬλ³λ μ λμ¨μ μμ€ν μ κ°λ₯ν μνλ₯Ό λͺ ννκ² μ μνμ¬ μ½λλ₯Ό λ μ½κ² μ΄ν΄νκ³ μ μ§λ³΄μν μ μκ² ν©λλ€. μνμ λͺ μμ ννμ μ½λμ λͺ νμ±μ λμ λλ€.
- ν₯μλ μ½λ μμ±: TypeScriptμ μΈν 리μΌμ€λ νμ¬ μνλ₯Ό κΈ°λ°μΌλ‘ μ§λ₯μ μΈ μ½λ μμ± μ μμ μ 곡νμ¬ μ€λ₯ λ°μ κ°λ₯μ±μ μ€μ΄κ³ κ°λ° μλλ₯Ό λμ λλ€.
ꡬλ³λ μ λμ¨μΌλ‘ μν λ¨Έμ μ μνκΈ°
μ£Όλ¬Έ μ²λ¦¬ μμ€ν μ΄λΌλ μ€μ©μ μΈ μμ λ₯Ό ν΅ν΄ ꡬλ³λ μ λμ¨μ μ¬μ©νμ¬ μν λ¨Έμ μ μ μνλ λ°©λ²μ μ€λͺ νκ² μ΅λλ€. μ£Όλ¬Έμ λκΈ° μ€(Pending), μ²λ¦¬ μ€(Processing), λ°°μ‘ μ€(Shipped), λ°°μ‘ μλ£(Delivered)μ κ°μ μνλ₯Ό κ°μ§ μ μμ΅λλ€.
1λ¨κ³: μν νμ μ μνκΈ°
λ¨Όμ , κ° μνμ λν κ°λ³ νμ μ μ μν©λλ€. κ° νμ μ ꡬλ³μ(discriminant) μν μ νλ `type` μμ±κ³Ό ν¨κ» μνλ³ λ°μ΄ν°λ₯Ό κ°μ§ κ²μ λλ€.
interface Pending {
type: "pending";
orderId: string;
customerName: string;
items: string[];
}
interface Processing {
type: "processing";
orderId: string;
assignedAgent: string;
}
interface Shipped {
type: "shipped";
orderId: string;
trackingNumber: string;
}
interface Delivered {
type: "delivered";
orderId: string;
deliveryDate: Date;
}
2λ¨κ³: ꡬλ³λ μ λμ¨ νμ μμ±νκΈ°
λ€μμΌλ‘, `|` (μ λμ¨) μ°μ°μλ₯Ό μ¬μ©νμ¬ μ΄λ¬ν κ°λ³ νμ λ€μ κ²°ν©νμ¬ κ΅¬λ³λ μ λμ¨μ λ§λλλ€.
type OrderState = Pending | Processing | Shipped | Delivered;
μ΄μ `OrderState`λ `Pending`, `Processing`, `Shipped`, λλ `Delivered` μ€ νλκ° λ μ μλ κ°μ λνλ λλ€. κ° μν λ΄μ `type` μμ±μ ꡬλ³μ μν μ νμ¬ TypeScriptκ° μ΄λ€μ ꡬλ³ν μ μκ² ν©λλ€.
μν μ ν μ²λ¦¬νκΈ°
μ΄μ μν λ¨Έμ μ μ μνμΌλ―λ‘, μν κ° μ νμ μν λ©μ»€λμ¦μ΄ νμν©λλ€. νμ¬ μνμ μ‘μ μ μ λ ₯μΌλ‘ λ°μ μλ‘μ΄ μνλ₯Ό λ°ννλ `processOrder` ν¨μλ₯Ό λ§λ€μ΄ λ³΄κ² μ΅λλ€.
interface Action {
type: string;
payload?: any;
}
function processOrder(state: OrderState, action: Action): OrderState {
switch (state.type) {
case "pending":
if (action.type === "startProcessing") {
return {
type: "processing",
orderId: state.orderId,
assignedAgent: action.payload.agentId,
};
}
return state; // μν λ³κ²½ μμ
case "processing":
if (action.type === "shipOrder") {
return {
type: "shipped",
orderId: state.orderId,
trackingNumber: action.payload.trackingNumber,
};
}
return state; // μν λ³κ²½ μμ
case "shipped":
if (action.type === "deliverOrder") {
return {
type: "delivered",
orderId: state.orderId,
deliveryDate: new Date(),
};
}
return state; // μν λ³κ²½ μμ
case "delivered":
// μ£Όλ¬Έμ΄ μ΄λ―Έ λ°°μ‘ μλ£λ¨, μΆκ° μμ
μμ
return state;
default:
// μ² μ μ± κ²μ¬λ‘ μΈν΄ μ΄ κ²½μ°λ λ°μνμ§ μμμΌ ν¨
return state; // λλ μ€λ₯ λ°μ
}
}
μ€λͺ
- `processOrder` ν¨μλ νμ¬ `OrderState`μ `Action`μ μ λ ₯μΌλ‘ λ°μ΅λλ€.
- `switch` λ¬Έμ μ¬μ©νμ¬ `state.type` ꡬλ³μλ₯Ό κΈ°λ°μΌλ‘ νμ¬ μνλ₯Ό κ²°μ ν©λλ€.
- κ° `case` λ΄λΆμμλ `action.type`μ νμΈνμ¬ μ ν¨ν μ νμ΄ νΈλ¦¬κ±°λλμ§ κ²°μ ν©λλ€.
- μ ν¨ν μ νμ΄ λ°κ²¬λλ©΄, μ μ ν `type`κ³Ό λ°μ΄ν°λ₯Ό κ°μ§ μλ‘μ΄ μν κ°μ²΄λ₯Ό λ°νν©λλ€.
- μ ν¨ν μ νμ΄ μμΌλ©΄, νμ¬ μνλ₯Ό λ°νν©λλ€ (λλ μνλ λμμ λ°λΌ μ€λ₯λ₯Ό λ°μμν¬ μ μμ΅λλ€).
- `default` μΌμ΄μ€λ μμ μ±μ μν΄ ν¬ν¨λμμΌλ©°, TypeScriptμ μ² μ μ± κ²μ¬ λλΆμ μ΄μμ μΌλ‘λ μ λ λλ¬νμ§ μμμΌ ν©λλ€.
μ² μ μ± κ²μ¬ νμ©νκΈ°
TypeScriptμ μ² μ μ± κ²μ¬λ μν λ¨Έμ μ λͺ¨λ κ°λ₯ν μνλ₯Ό μ²λ¦¬νλλ‘ λ³΄μ₯νλ κ°λ ₯ν κΈ°λ₯μ λλ€. λ§μ½ `OrderState` μ λμ¨μ μλ‘μ΄ μνλ₯Ό μΆκ°νκ³ `processOrder` ν¨μλ₯Ό μ λ°μ΄νΈνλ κ²μ μμΌλ©΄, TypeScriptλ μ€λ₯λ₯Ό νμν κ²μ λλ€.
μ² μ μ± κ²μ¬λ₯Ό νμ±ννλ €λ©΄ `never` νμ μ μ¬μ©ν μ μμ΅λλ€. switch λ¬Έμ `default` μΌμ΄μ€ λ΄λΆμμ μνλ₯Ό `never` νμ μ λ³μμ ν λΉνμΈμ.
function processOrder(state: OrderState, action: Action): OrderState {
switch (state.type) {
// ... (μ΄μ μΌμ΄μ€λ€) ...
default:
const _exhaustiveCheck: never = state;
return _exhaustiveCheck; // λλ μ€λ₯ λ°μ
}
}
`switch` λ¬Έμ΄ λͺ¨λ κ°λ₯ν `OrderState` κ°μ μ²λ¦¬νλ©΄, `_exhaustiveCheck` λ³μλ `never` νμ μ΄ λμ΄ μ½λκ° μ»΄νμΌλ©λλ€. κ·Έλ¬λ `OrderState` μ λμ¨μ μλ‘μ΄ μνλ₯Ό μΆκ°νκ³ `switch` λ¬Έμμ μ΄λ₯Ό μ²λ¦¬νλ κ²μ μμΌλ©΄, `_exhaustiveCheck` λ³μλ λ€λ₯Έ νμ μ΄ λμ΄ TypeScriptκ° μ»΄νμΌ νμ μ€λ₯λ₯Ό λ°μμμΌ λλ½λ μΌμ΄μ€λ₯Ό μλ €μ€λλ€.
μ€μ©μ μΈ μμ λ° μμ© λΆμΌ
ꡬλ³λ μ λμ¨μ λ¨μν μ£Όλ¬Έ μ²λ¦¬ μμ€ν μ λμ΄ λ€μν μλ리μ€μ μ μ©ν μ μμ΅λλ€:
- UI μν κ΄λ¦¬: UI μ»΄ν¬λνΈμ μν(μ: λ‘λ©, μ±κ³΅, μ€λ₯) λͺ¨λΈλ§.
- λ€νΈμν¬ μμ² μ²λ¦¬: λ€νΈμν¬ μμ²μ μ¬λ¬ λ¨κ³(μ: μ΄κΈ°, μ§ν μ€, μ±κ³΅, μ€ν¨) νν.
- νΌ μ ν¨μ± κ²μ¬: νΌ νλμ μ 체 νΌ μνμ μ ν¨μ± μΆμ .
- κ²μ κ°λ°: κ²μ μΊλ¦ν°λ κ°μ²΄μ μ¬λ¬ μν μ μ.
- μΈμ¦ νλ¦: μ¬μ©μ μΈμ¦ μν(μ: λ‘κ·ΈμΈ, λ‘κ·Έμμ, μΈμ¦ λκΈ°) κ΄λ¦¬.
μμ : UI μν κ΄λ¦¬
APIμμ λ°μ΄ν°λ₯Ό κ°μ Έμ€λ UI μ»΄ν¬λνΈμ μνλ₯Ό κ΄λ¦¬νλ κ°λ¨ν μμ λ₯Ό μ΄ν΄λ³΄κ² μ΅λλ€. λ€μκ³Ό κ°μ μνλ₯Ό μ μν μ μμ΅λλ€:
interface Initial {
type: "initial";
}
interface Loading {
type: "loading";
}
interface Success {
type: "success";
data: T;
}
interface Error {
type: "error";
message: string;
}
type UIState = Initial | Loading | Success | Error;
function renderUI(state: UIState): React.ReactNode {
switch (state.type) {
case "initial":
return λ°μ΄ν°λ₯Ό λ‘λνλ €λ©΄ λ²νΌμ ν΄λ¦νμΈμ.
;
case "loading":
return λ‘λ© μ€...
;
case "success":
return {JSON.stringify(state.data, null, 2)}
;
case "error":
return μ€λ₯: {state.message}
;
default:
const _exhaustiveCheck: never = state;
return _exhaustiveCheck;
}
}
μ΄ μμ λ ꡬλ³λ μ λμ¨μ μ¬μ©νμ¬ UI μ»΄ν¬λνΈμ μ¬λ¬ μνλ₯Ό ν¨κ³Όμ μΌλ‘ κ΄λ¦¬νκ³ , νμ¬ μνμ λ°λΌ UIκ° μ¬λ°λ₯΄κ² λ λλ§λλλ‘ λ³΄μ₯νλ λ°©λ²μ 보μ¬μ€λλ€. `renderUI` ν¨μλ κ° μνλ₯Ό μ μ νκ² μ²λ¦¬νμ¬ UIλ₯Ό κ΄λ¦¬νλ λͺ ννκ³ νμ -μΈμ΄νν λ°©λ²μ μ 곡ν©λλ€.
ꡬλ³λ μ λμ¨ μ¬μ©μ μν λͺ¨λ² μ¬λ‘
TypeScript νλ‘μ νΈμμ ꡬλ³λ μ λμ¨μ ν¨κ³Όμ μΌλ‘ νμ©νλ €λ©΄ λ€μ λͺ¨λ² μ¬λ‘λ₯Ό κ³ λ €νμΈμ:
- μλ―Έ μλ ꡬλ³μ μ΄λ¦ μ ν: μμ±μ λͺ©μ μ λͺ ννκ² λνλ΄λ ꡬλ³μ μ΄λ¦μ μ ννμΈμ (μ: `type`, `state`, `status`).
- μν λ°μ΄ν° μ΅μν: κ° μνλ ν΄λΉ νΉμ μνμ κ΄λ ¨λ λ°μ΄ν°λ§ ν¬ν¨ν΄μΌ ν©λλ€. μνμ λΆνμν λ°μ΄ν°λ₯Ό μ μ₯νμ§ λ§μΈμ.
- μ² μ μ± κ²μ¬ μ¬μ©: νμ μ² μ μ± κ²μ¬λ₯Ό νμ±ννμ¬ λͺ¨λ κ°λ₯ν μνλ₯Ό μ²λ¦¬νλλ‘ λ³΄μ₯νμΈμ.
- μν κ΄λ¦¬ λΌμ΄λΈλ¬λ¦¬ μ¬μ© κ³ λ €: 볡μ‘ν μν λ¨Έμ μ κ²½μ°, μν μ°¨νΈ, κ³μΈ΅μ μν, λ³λ ¬ μνμ κ°μ κ³ κΈ κΈ°λ₯μ μ 곡νλ XStateμ κ°μ μ μ© μν κ΄λ¦¬ λΌμ΄λΈλ¬λ¦¬ μ¬μ©μ κ³ λ €ν΄ λ³΄μΈμ. κ·Έλ¬λ λ κ°λ¨ν μλ리μ€μμλ ꡬλ³λ μ λμ¨μΌλ‘λ μΆ©λΆν μ μμ΅λλ€.
- μν λ¨Έμ λ¬Έμν: μ μ§λ³΄μμ±κ³Ό νμ μ κ°μ νκΈ° μν΄ μν λ¨Έμ μ μ¬λ¬ μν, μ ν λ° μ‘μ μ λͺ ννκ² λ¬ΈμννμΈμ.
κ³ κΈ κΈ°λ²
μ‘°κ±΄λΆ νμ (Conditional Types)
μ‘°κ±΄λΆ νμ μ ꡬλ³λ μ λμ¨κ³Ό κ²°ν©νμ¬ ν¨μ¬ λ κ°λ ₯νκ³ μ μ°ν μν λ¨Έμ μ λ§λ€ μ μμ΅λλ€. μλ₯Ό λ€μ΄, μ‘°κ±΄λΆ νμ μ μ¬μ©νμ¬ νμ¬ μνμ λ°λΌ ν¨μμ λ€λ₯Έ λ°ν νμ μ μ μν μ μμ΅λλ€.
function getData(state: UIState): T | undefined {
if (state.type === "success") {
return state.data;
}
return undefined;
}
μ΄ ν¨μλ κ°λ¨ν `if` λ¬Έμ μ¬μ©νμ§λ§, νΉμ νμ μ΄ νμ λ°νλλλ‘ λ³΄μ₯νκΈ° μν΄ μ‘°κ±΄λΆ νμ μ μ¬μ©νμ¬ λ κ²¬κ³ νκ² λ§λ€ μ μμ΅λλ€.
μ νΈλ¦¬ν° νμ (Utility Types)
TypeScriptμ μ νΈλ¦¬ν° νμ μΈ `Extract`μ `Omit`μ ꡬλ³λ μ λμ¨μΌλ‘ μμ ν λ μ μ©ν μ μμ΅λλ€. `Extract`λ 쑰건μ λ°λΌ μ λμ¨ νμ μμ νΉμ λ©€λ²λ₯Ό μΆμΆν μ μκ² νκ³ , `Omit`μ νμ μμ μμ±μ μ κ±°ν μ μκ² ν©λλ€.
// UIState μ λμ¨μμ "success" μν μΆμΆ
type SuccessState = Extract, { type: "success" }>;
// Error μΈν°νμ΄μ€μμ 'message' μμ± μλ΅
type ErrorWithoutMessage = Omit;
λ€μν μ°μ λΆμΌμ μ€μ μ¬λ‘
ꡬλ³λ μ λμ¨μ νμ λ€μν μ°μ κ³Ό μ ν리μΌμ΄μ μμμΌλ‘ νμ₯λ©λλ€:
- μ μμκ±°λ (κΈλ‘λ²): κΈλ‘λ² μ μμκ±°λ νλ«νΌμμ μ£Όλ¬Έ μνλ "κ²°μ λκΈ°", "μ²λ¦¬μ€", "λ°°μ‘μ€", "μ΄μ‘μ€", "λ°°μ‘μλ£", "μ·¨μ"μ κ°μ μνλ₯Ό μ²λ¦¬νλ ꡬλ³λ μ λμ¨μΌλ‘ ννλ μ μμ΅λλ€. μ΄λ₯Ό ν΅ν΄ λ€μν λ°°μ‘ λ¬Όλ₯λ₯Ό κ°μ§ μ¬λ¬ κ΅κ°μ κ±Έμ³ μ νν μΆμ κ³Ό μν΅μ 보μ₯ν©λλ€.
- κΈμ΅ μλΉμ€ (κ΅μ μνμ ): "μΉμΈλκΈ°", "μΉμΈλ¨", "μ²λ¦¬μ€", "μλ£", "μ€ν¨"μ κ°μ κ±°λ μνλ₯Ό κ΄λ¦¬νλ κ²μ λ§€μ° μ€μν©λλ€. ꡬλ³λ μ λμ¨μ μ΄λ¬ν μνλ₯Ό κ²¬κ³ νκ² μ²λ¦¬νλ©° λ€μν κ΅μ μν κ·μ μ μ€μνλ λ°©λ²μ μ 곡ν©λλ€.
- ν¬μ€μΌμ΄ (μ격 νμ λͺ¨λν°λ§): "μ μ", "μ£Όμ", "μκΈ"κ³Ό κ°μ μνλ₯Ό μ¬μ©νμ¬ νμμ κ±΄κ° μνλ₯Ό νννλ©΄ μκΈ°μ μ ν κ°μ μ΄ κ°λ₯ν©λλ€. μ μΈκ³μ λΆμ°λ ν¬μ€μΌμ΄ μμ€ν μμ ꡬλ³λ μ λμ¨μ μμΉμ κ΄κ³μμ΄ μΌκ΄λ λ°μ΄ν° ν΄μμ 보μ₯ν μ μμ΅λλ€.
- λ¬Όλ₯ (κΈλ‘λ² κ³΅κΈλ§): κ΅κ²½μ λλ λ°°μ‘ μν μΆμ μ 볡μ‘ν μν¬νλ‘μ°λ₯Ό ν¬ν¨ν©λλ€. "ν΅κ΄μ€", "μ΄μ‘μ€", "λ¬Όλ₯μΌν°λμ°©", "λ°°μ‘μλ£"μ κ°μ μνλ ꡬλ³λ μ λμ¨ κ΅¬νμ μλ²½νκ² μ ν©ν©λλ€.
- κ΅μ‘ (μ¨λΌμΈ νμ΅ νλ«νΌ): "λ±λ‘λ¨", "μ§νμ€", "μλ£", "μκ°ν¬κΈ°"μ κ°μ μνλ‘ κ°μ’ λ±λ‘ μνλ₯Ό κ΄λ¦¬νλ©΄, μ μΈκ³μ λ€μν κ΅μ‘ μμ€ν μ μ μν μ μλ κ°μνλ νμ΅ κ²½νμ μ 곡ν μ μμ΅λλ€.
κ²°λ‘
TypeScript ꡬλ³λ μ λμ¨μ μν λ¨Έμ μ ꡬμΆνλ κ°λ ₯νκ³ νμ -μΈμ΄νν λ°©λ²μ μ 곡ν©λλ€. κ°λ₯ν μνμ μ νμ λͺ ννκ² μ μν¨μΌλ‘μ¨ λ κ²¬κ³ νκ³ , μ μ§λ³΄μνκΈ° μ¬μ°λ©°, μ΄ν΄νκΈ° μ¬μ΄ μ½λλ₯Ό λ§λ€ μ μμ΅λλ€. νμ μμ μ±, μ² μ μ± κ²μ¬, ν₯μλ μ½λ μμ±μ μ‘°ν©μ ꡬλ³λ μ λμ¨μ 볡μ‘ν μν κ΄λ¦¬λ₯Ό λ€λ£¨λ λͺ¨λ TypeScript κ°λ°μμκ² κ·μ€ν λκ΅¬λ‘ λ§λλλ€. λ€μ νλ‘μ νΈμμ ꡬλ³λ μ λμ¨μ μ±ννκ³ νμ -μΈμ΄νν μν κ΄λ¦¬μ μ΄μ μ μ§μ κ²½νν΄ λ³΄μΈμ. μ μμκ±°λμμ ν¬μ€μΌμ΄, λ¬Όλ₯μμ κ΅μ‘μ μ΄λ₯΄κΈ°κΉμ§ λ€μν μμμμ 보μ¬μ£Όμλ―μ΄, ꡬλ³λ μ λμ¨μ ν΅ν νμ -μΈμ΄ν μν κ΄λ¦¬ μμΉμ 보νΈμ μΌλ‘ μ μ© κ°λ₯ν©λλ€.
κ°λ¨ν UI μ»΄ν¬λνΈλ₯Ό λ§λ€λ 볡μ‘ν κΈ°μ μ© μ ν리μΌμ΄μ μ λ§λ€λ , ꡬλ³λ μ λμ¨μ μνλ₯Ό λ ν¨κ³Όμ μΌλ‘ κ΄λ¦¬νκ³ λ°νμ μ€λ₯μ μνμ μ€μ΄λ λ° λμμ΄ λ μ μμ΅λλ€. κ·Έλ¬λ, TypeScriptλ‘ νμ -μΈμ΄νν μν λ¨Έμ μ μΈκ³λ₯Ό ννν΄ λ³΄μΈμ!